package com.ruoyi.learn.java.concurrent;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomUtils;

import java.util.concurrent.CyclicBarrier;

/**
 * 2. CyclicBarrier（循环屏障）
 * 基本概念
 * 允许一组线程互相等待，直到到达某个公共屏障点
 *
 * 与CountDownLatch不同，它可以重置后重复使用
 *
 * 可以设置一个到达屏障点后执行的动作（Runnable）
 *
 * 主要方法
 * java
 * // 构造方法，parties表示屏障拦截的线程数量
 * public CyclicBarrier(int parties)
 *
 * // 带屏障动作的构造方法
 * public CyclicBarrier(int parties, Runnable barrierAction)
 *
 * // 线程调用await()表示已到达屏障
 * public int await()
 *
 * // 带超时的await
 * public int await(long timeout, TimeUnit unit)
 *
 * // 重置屏障
 * public void reset()
 *
 * // 获取等待的线程数量
 * public int getNumberWaiting()
 *
 * // 获取参与方数量
 * public int getParties()
 *
 * 典型应用场景
 * 多线程计算数据，最后合并计算结果
 *
 * 需要多个线程到达某个状态后再一起继续执行
 *
 *
 */
@Slf4j
public class CyclicBarrierDemo {
    public static void main(String[] args) {
        int threadCount = 6;
        CyclicBarrier barrier = new CyclicBarrier(threadCount, () -> {
            System.out.println("所有线程已到达屏障，执行屏障动作");
        });

        for (int i = 0; i < threadCount; i++) {
            new Thread(() -> {
                try {
                    System.out.println(Thread.currentThread().getName() + " 到达屏障点");
                    try {
                        Thread.sleep(RandomUtils.nextLong(0, 6000));
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }

                    barrier.await();
                    System.out.println(Thread.currentThread().getName() + " 继续执行");
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }, "Thread-" + i).start();
        }
    }
}